<template>
  <div>
    <!-- 编辑 -->
    <el-upload
      v-if="edit"
      ref="upload"
      :file-list="currentValue"
      :show-file-list="!multiple"
      :action="`${action}`"
      :auto-upload="!multiple"
      :data="{...data}"
      :headers="headers"
      :before-upload="handleBeforeUpload"
      :on-success="handleOnSuccess"
      :on-remove="handleOnRemove"
      :before-remove="handleBeforeRemove"
      :accept="accept"
      :on-preview="handleOnPreview"
      :multiple="multiple"
      :limit="limit"
      :on-change="handleOnChange"
      :class="className"
    >
      <el-button icon="el-icon-upload" :loading="loading" size="small" type="primary">{{ buttonText }}</el-button>
      <div slot="tip" class="el-upload__tip">
        <div v-if="edit && showTipText" class="el-upload__tip_text">
          文件格式为{{ acceptList.join('/') }},文件大小不超过{{ size }}M,文件个数不超过{{ limit }}个
        </div>
        <!-- 多选专用文件列表 -->
        <FileList v-if="multiple" :file-list="currentValue" @on-preview="handleOnPreview"
                  @on-delete="handleOnRemoveMul"
        ></FileList>
      </div>
    </el-upload>
    <!-- 查看 -->
    <template v-else>
      <div v-for="(item,index) in currentValue" :key="index">
        <div class="primary-color pointer" @click="handleOnPreview(item)">{{ item.name || item.fileName || item.originName || '文件' }}</div>
      </div>
    </template>
    <imageFilePreview ref="imageFilePreview"></imageFilePreview>
  </div>
</template>
<script>
import imageFilePreview from './imageFilePreview.vue'
import { getToken } from '@/utils/auth'
import request from '@/utils/request'
import FileList from './FileList.vue'

export default {
  name: 'UploadFile',
  components: {
    imageFilePreview,
    FileList
  },
  props: {
    data: {
      type: Object,
      default() {
        return {}
      }
    },
    limit: {
      type: Number,
      default: 5
    },
    action: {
      type: String,
      default: '/api/sys/oss/upload'
    },
    removeAction: {
      type: String,
      default: '/rxt/attach/remove'
    },
    accept: {
      type: String,
      default: '.png, .jpg, .jpeg, .gif, .pdf, .doc, .docx, .xls, .xlsx'
    },
    size: {
      type: Number,
      default: 5
    },
    multiple: {
      type: Boolean,
      default: false
    },
    fileList: {
      type: Array,
      default() {
        return []
      }
    },
    className: {
      type: String,
      default: 'upload-file'
    },
    edit: {
      type: Boolean,
      default: true
    },
    buttonText: {
      type: String,
      default: '上传'
    },
    showTipText: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      loading: false,
      addNum: 0,
      headers: { Authorization: 'Bearer ' + getToken() },
      currentValue: this.fileList || [],
      acceptList: this.accept.split('.').join('').split(' ').join('').split(','),
      VUE_APP_BASE_API: process.env.VUE_APP_BASE_API
    }
  },
  watch: {
    fileList: {
      handler(val) {
        this.currentValue = val || []
        this.currentValue.forEach(v => this.$set(v, 'name', v.fileName))
      }
    }
  },
  computed: {},
  created() {
  },
  methods: {
    handleOnPreview(item) {
      if (item) this.$refs.imageFilePreview.openPreview(item)
    },
    // 单选（删除前判断）
    async handleBeforeRemove(file) {
      const id = file.id
      if (!id) return
      const params = [id]
      this.loading = true
      try {
        await request({
          url: this.removeAction,
          method: 'post',
          data: params
        })
        this.$message.success('删除成功')
        return true
      } catch (error) {
        return false
      } finally {
        this.loading = false
      }
    },
    // 单选
    async handleOnRemove(file) {
      const i = this.currentValue.findIndex(x => x.url === file.url)

      if (i > -1) {
        this.currentValue.splice(i, 1)
        this.$emit('on-remove', i)
      }
    },
    // 多选
    async handleOnRemoveMul(file) {
      const id = file.id
      const params = [id]
      this.loading = true
      try {
        await request({
          url: this.removeAction,
          method: 'post',
          data: params
        })
        this.$message.success('删除成功')
        const i = this.currentValue.findIndex(x => x.id === id)
        this.currentValue.splice(i, 1)
        this.$emit('on-remove', i)
      } catch (error) {

      } finally {
        this.loading = false
      }
    },
    // 单选
    handleBeforeUpload(file) {
      if (this.multiple) return
      this.loading = true
      const isTypeOk = this.acceptList.includes(file.name.substring(file.name.lastIndexOf('.') + 1))
      const isSizeOk = file.size / 1024 / 1024 < this.size
      if (!isTypeOk) {
        this.$message.error(`文件格式不正确 请上传${this.acceptList.join('/')}格式文件`)
        this.loading = false
        return false
      } else if (!isSizeOk) {
        this.$message.error(`上传文件大小不能超过${this.size}MB`)
        this.loading = false
        return false
      }
      return true
    },
    // 单选
    handleOnSuccess(response) {
      if (this.multiple) return
      this.loading = false
      if (response.code === 200) {
        this.$message.success('上传成功')
        this.currentValue.push(response.data)
        this.$emit('on-success', this.currentValue)
      } else {
        this.$message.error(response.msg || '文件上传失败，请检查文件大小或类型')
      }
    },
    // 多选
    handleOnChange(file, fileList) { // 这一步一定要写
      if (!this.multiple) return
      const upload_img = document.getElementsByClassName(this.className)
      let uploadNum = 0
      if (upload_img && upload_img.length > 0) {
        const upload = upload_img[0].getElementsByTagName('input')
        if (upload && upload.length > 0 && upload[0].files && upload[0].files.length > 0) {
          uploadNum = upload[0].files.length
        }
      }
      this.addNum++
      if (this.addNum == uploadNum) {
        this.submitUpload()
      }
    },
    // 文件上传处理
    submitUpload() {
      let { uploadFiles, action, data } = this.$refs.upload
      let newUploadFiles = []
      let typeErrorFiles = []
      let sizeErrorFiles = []
      typeErrorFiles = uploadFiles.filter(v => !this.acceptList.includes(v.name.substring(v.name.lastIndexOf('.') + 1)))
      sizeErrorFiles = uploadFiles.filter(v => v.size / 1024 / 1024 > this.size)
      newUploadFiles = uploadFiles.filter(v => this.acceptList.includes(v.name.substring(v.name.lastIndexOf('.') + 1)) && v.size / 1024 / 1024 <= this.size)
      if (typeErrorFiles.length) {
        this.$message.error(`文件格式不正确, 请上传${this.acceptList.join('/')}格式文件!已自动过滤`)
      } else if (sizeErrorFiles.length) {
        this.$message.error(`上传文件大小不能超过${this.size}MB!已自动过滤`)
      }
      if (!newUploadFiles.length) {
        this.$refs.upload.clearFiles()
        this.addNum = 0
        return
      }
      console.log(newUploadFiles)
      this.uploadFiles({
        uploadFiles: newUploadFiles,
        action,
        data
      })
    },
    uploadFiles({ uploadFiles, data, action }) {
      let formData = new FormData()
      // 文件对象
      uploadFiles.map(file => formData.append('files', file.raw))
      // 附件参数
      const newData = { ...data, sceneId: this.sceneId, sceneKey: this.sceneKey }
      if (newData) {
        for (let key in newData) {
          formData.append(key, newData[key])
        }
      }
      this.loading = true
      request({
        url: this.action,
        method: 'post',
        data: formData
      }).then((res) => {
        //获取文件列表返回callback
        this.$message.success('上传成功')
        this.currentValue.push(...res.data)
        this.$emit('on-success', res.data)
      }).finally(() => {

        this.$refs.upload.clearFiles()
        this.loading = false
        this.addNum = 0
      })
    }
  }
}
</script>

<style lang="scss">
.el-upload__tip_text {
  line-height: 12px;
}
</style>
